package setting

import (
	"log"
	"os"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

var (
	Config *Conf
)

type Conf struct {
	Server   Server   `mapstructure:"server" yaml:"server"`     // api服务配置信息
	Database Database `mapstructure:"database" yaml:"database"` // 数据库配置信息
	Redis    Redis    `mapstructure:"redis" yaml:"redis"`       // redis配置信息
	App      App      `mapstructure:"app" yaml:"app"`           // 程序配置信
}

type Server struct {
	Port         string        `mapstructure:"port" yaml:"port"`
	ReadTimeout  time.Duration `mapstructure:"read-timeout" yaml:"read-timeout"`
	WriteTimeout time.Duration `mapstructure:"write-timeout" yaml:"write-timeout"`
}

type App struct {
	RunMode     string `mapstructure:"run-mode" yaml:"run-mode"`
	PageSize    int    `mapstructure:"page-size" yaml:"page-size"`
	IdentityKey string `mapstructure:"identity-key" yaml:"identity-key"`
	LogPath     string `mapstructure:"log-path" yaml:"log-path"`
	AesKey      string `mapstructure:"aes-key" yaml:"aes-key"`
}

type Database struct {
	Type        string `mapstructure:"type" yaml:"type"`
	User        string `mapstructure:"user" yaml:"user"`
	Password    string `mapstructure:"password" yaml:"password"`
	Host        string `mapstructure:"host" yaml:"host"`
	Name        string `mapstructure:"name" yaml:"name"`
	TablePrefix string `mapstructure:"table-prefi" yaml:"table-prefix"`
}

type Redis struct {
	Addr        string        `mapstructure:"addr" yaml:"addr"`
	Pass        string        `mapstructure:"pass" yaml:"pass"`
	DB          int           `mapstructure:"db" yaml:"db"`
	Timeout     time.Duration `mapstructure:"timeout" yaml:"timeout"`
	ExpiredTime int           `mapstructure:"expired-tim" yaml:"expired-time"`
}

func init() {
	Config = getConf()
	log.Println("[Setting] Config init success")
}
func getConf() *Conf {
	configPath := "./config/config.yml"
	// 生产环境可以通过设置环境变量来改变配置文件路径
	if configEnv := os.Getenv("VIPER_CONFIG"); configEnv != "" {
		configPath = configEnv
	}
	// 初始化 viper
	v := viper.New()
	v.SetConfigFile(configPath)
	v.SetConfigType("yaml")

	if err := v.ReadInConfig(); err != nil {
		log.Println("[Setting] config error: ", err)
	}
	var c *Conf = new(Conf)
	// var c *Conf  下面用 &c也可以取到值
	// 监听配置文件
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("夭寿啦~配置文件被人修改啦... config file changed:", in.Name)
		// 重载配置
		if err := v.Unmarshal(c); err != nil {
			log.Println("[Setting] yaml unmarshal error: ", err)
		}
	})
	// 将配置赋值给全局变量
	if err := v.Unmarshal(c); err != nil {
		log.Println("[Setting] yaml unmarshal error: ", err)
	}
	return c
}
